#coding=utf-8
#
# Copyright (C) 2014  NianNian TECH Co., Ltd. All rights reserved.
# Created on May 9, 2014, by Junn
#
from core.views import CustomAPIView
from core.decorators import login_required_pro, login_required_mtd
from posts.forms import PostForm
from utils import http, logs
from families.models import Family
from utils.http import Response
from posts.serializers import PagingCommentSerializer
from utils.eggs import handle_paging, rename_file
from posts.models import Post, Comment, CommentMsg
from posts.signals import s_post_added, s_comment_me
from core.serializers import serialize_response
from posts.tasks import CountUnreadPostsThreadManager
import posts
from users.models import User
from rest_framework.decorators import api_view


class PostView(CustomAPIView):
    '''批量操作单个动态'''

    def get(self, req, pid):
        try:
            post = Post.objects.get(id=int(pid))
            post.comments = list(post.get_all_comments())
            return serialize_response(post)
        except Post.DoesNotExist:    
            return http.resp('object_not_found', 'pid:%s' % pid)
 
    def delete(self, req, pid):
        try:
            post = Post.objects.get(id=int(pid))
            if post.author == req.user or req.user.is_family_creator():
                post.delete() 
                return http.ok()
            else:
                return http.resp('permission_denied')     
        except Post.DoesNotExist:
            return http.resp('object_not_found', 'pid:%s' % pid)
        except Exception, e:
            logs.error('delete post error: %s' % e)
            return http.failed()
        

class PostsAction(CustomAPIView):
    '''批量操作动态'''
    
    @login_required_pro
    def get(self, req):
        '''返回动态列表, 带分页
        @param fid: 家庭id, fid若不为空, 则返回某家庭动态列表. 
        '''
        last_item_time = req.GET.get('last_item_time', '')
        limit_count = req.GET.get('limit_count', 10)
        
        q = req.GET.get('q', '')  #?q=me
        if q == 'me':  #当前登录用户发布的动态
            posts = Post.objects.get_user_published(req.user, item_time=last_item_time)
        else:  # 传入的指定家庭的动态   
            fid = req.REQUEST.get('fid')
            family = Family.objects.get_cached(fid)
            if not family:
                return http.resp('object_not_found', 'family: %s' % fid)            
            posts = family.get_paged_posts(last_item_time, limit_count)
            if not last_item_time:      #刷新动态, 或首次进入动态页, 未读动态计数清0
                family.clear_unread_count(req.user)            
        
        if not posts: return Response([])
        for p in posts:
            p.comments = list(p.get_all_comments())  # TODO: 需要优化, 以免多次查询DB...
        
        # TODO: 是否家庭成员的判断
        return serialize_response(list(posts))
    
    @login_required_pro
    def post(self, req):
        '''发布一条新动态, fid为必须的参数'''
        
        fid = req.POST.get('fid', '')
        if not fid:
            return http.failed('缺乏参数fid')
        family = Family.objects.get_cached(fid)
        if not family:
            return http.object_not_found()
        
        # TODO: 是否家庭成员的判断
        form = PostForm(req.user, family, req.POST, req.FILES) #注意POST与FILES的传入顺序
        if form.is_valid():
            post = form.save()
            s_post_added.send(sender=post.__class__, user=req.user, family=family, post=post)
            logs.info('signal s_post_added sent')
            return serialize_response(post)
        
        logs.error('参数错误: %s' % form.errors)
        return http.failed('参数错误')  
    
class PostCommentsAction(CustomAPIView):
    '''批量操作动态的评论'''
    
    @login_required_pro
    def post(self, req, pid):
        '''添加新评论, 或回复某条评论'''
        
        reply_to = req.POST.get('reply_to', '') #被回复者id
        info, aud = req.POST.get('info', ''), req.FILES.get('aud', None)
        aud_len = req.POST.get('aud_len', 0)
        
        if not info.strip() and not aud:
            return http.resp('params_error')
        try:
            fpost = Post.objects.get(id=int(pid))
        except Post.DoesNotExist:
            logs.info('Post not found: %s' % pid)
            return http.object_not_found()
        
        if aud:#若是语音评论, 则改名
            rename_file(aud)
            
        data = {'author': req.user, 'info': info, 'aud': aud, 'aud_len': aud_len}
        rel_to = fpost.author #若A回复B的评论, 则rel_to=B, 默认rel_to=动态的发布者(此时为添加评论) 
        reply_to_obj = None
        if reply_to:
            reply_to_obj = User.objects.get_cached(reply_to)
            data.update({'reply_to': reply_to_obj})
            rel_to = reply_to_obj
            
        comment = fpost.add_comment(data)
        
        ## 1.若为回复, 则必然要向被回复者发送提醒(因为不可自己回复自己) 
        ## 2. 若为评论, 则需判断评论者与动态发布者是否为同一人
        if reply_to_obj or comment.author != fpost.author: 
            s_comment_me.send(sender=comment.__class__, rel_to=rel_to, comment=comment)
          
        return serialize_response(comment)
    
    def get(self, req, pid):
        '''返回某条动态的评论列表'''
        try:
            fpost = Post.objects.get(id=int(pid))
        except Post.DoesNotExist:
            logs.error('Post not exists: %s' % pid)
            return http.object_not_found()    
        
        items = handle_paging(req, fpost.get_all_comments())
        return Response(PagingCommentSerializer(instance=items, results_field_name='comments').data)
    
@api_view(['GET'])    
@login_required_mtd    
def get_relcomment_msgs(req):
    ''' 返回与当前登录家庭用户相关的评论或回复消息列表 
    @param t:    0-历史消息(已读), 1-新消息(未读), 2-全部消息(未读和已读). 默认为1
    '''
    t = req.REQUEST.get('t', '1')     # 默认为新消息, 为兼容旧客户端版本 
    last_time = req.REQUEST.get('last_item_time')
    
    
    if t not in ('0', '1', '2'):
        return http.failed(u'无效的参数值: t=%s' % t)
    
    if t == '0':
        rel_msgs = CommentMsg.objects.get_checked_relcomment_msgs(req.user, last_time)
        return serialize_response(list(rel_msgs))
    
    if t == '1':
        unchecked_msgs_queryset = CommentMsg.objects.get_relcomment_msgs(req.user, last_time)
        rel_msgs = list(unchecked_msgs_queryset)  # 强制执行django查询, 以便得到数据列表的拷贝不被下一句update影响
        
        # 获取到消息列表后将消息置为已读, 仅当读取新消息列表时执行该更新
        try:
            CommentMsg.objects.check_msgs(req.user)
        except Exception, e:
            logs.error('check relcomment_msgs error:  \n %s' % e)
            
        return serialize_response(rel_msgs)
    
    # t == '2'
    rel_msgs = CommentMsg.objects.get_all_relcomment_msgs(req.user, last_time)
    return serialize_response(list(rel_msgs))
     
    
class PostCommentView(CustomAPIView):
    '''单个操作某动态评论'''
    
    def get(self, req, cid):
        pass
    
    @login_required_pro
    def delete(self, req, pid, cid):
        try:
            comment = Comment.objects.get(id=int(cid))
            if not req.user == comment.author: return http.resp('permission_denied')  
            comment.delete()
            return http.ok()
        except Comment.DoesNotExist:
            return http.failed('评论不存在或已被删除')
        except Exception, e:
            logs.error('%s' % e)
            return http.failed()
             

UPC_THREAD = None      
      
def start_count_posts_thread(req):
    action = req.REQUEST.get('a', None)  # 1-start, 0-stop
    
    if action not in ('1', '0'): 
        return http.failed('unknown action: %s' % action) 
    
    upc_thread = posts.views.UPC_THREAD
    if action == '1':
        if not upc_thread or not upc_thread.is_started():
            upc_thread = CountUnreadPostsThreadManager(name='unread_posts_counting_thread')
            upc_thread.start()
            posts.views.UPC_THREAD = upc_thread
        else: 
            return http.ok({'thread has been started, dont need to start again': 0})    
    else:
        if upc_thread and upc_thread.is_started():
            upc_thread.stop()  
            return http.ok({'thread stoped': 0})
        else:
            return http.failed('''upc_thread is None, or can't stop the thread not started''' )    
            
    return http.ok({'thread started:': upc_thread.getName()})

